import os
import shutil
import numpy as np
import pandas as pd
import tensorflow as tf
import matplotlib.pyplot as plt
import random
import plotly.express as px
import cv2 as cv2
import scipy as sp
from shutil import copyfile
from tensorflow.keras.layers import Conv2D,Add,MaxPooling2D, Dense, BatchNormalization,Input,Flatten, Dropout
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import LearningRateScheduler
from tensorflow.keras.preprocessing.image import ImageDataGenerator
source_path = 'C:/Users/alasmar/Downloads/cats-vs-dogs/PetImages'
source_path_cats = os.path.join(source_path, 'Cat')
source_path_dogs = os.path.join(source_path, 'Dog')
# os.listdir returns a list containing all files under the given path
print(f"There are {len(os.listdir(source_path_dogs))} images of dogs.")
print(f"There are {len(os.listdir(source_path_cats))} images of cats.")
There are 12501 images of dogs. There are 12501 images of cats.
#Define data path
CAT_DIR = 'C:/Users/alasmar/Downloads/cats-vs-dogs/PetImages/Cat'
DOG_DIR = 'C:/Users/alasmar/Downloads/cats-vs-dogs/PetImages/Dog'
try:
os.mkdir('C:/Users/alasmar/Downloads/cats-v-dogs')
os.mkdir('C:/Users/alasmar/Downloads/cats-v-dogs/training')
os.mkdir('C:/Users/alasmar/Downloads/cats-v-dogs/validation')
os.mkdir('C:/Users/alasmar/Downloads/cats-v-dogs/training/cats')
os.mkdir('C:/Users/alasmar/Downloads/cats-v-dogs/training/dogs')
os.mkdir('C:/Users/alasmar/Downloads/cats-v-dogs/validation/cats')
os.mkdir('C:/Users/alasmar/Downloads/cats-v-dogs/validation/dogs')
except OSError:
print('Error failed to make directory')
class_names = ['Cat', 'Dog']
n_cats = len(os.listdir('C:/Users/alasmar/Downloads/cats-vs-dogs/PetImages/Cat'))
n_dogs = len(os.listdir('C:/Users/alasmar/Downloads/cats-vs-dogs/PetImages/Dog'))
n_images = [n_cats, n_dogs]
px.pie(names=class_names, values=n_images)
TRAINING_DIR = "C:/Users/alasmar/Downloads/cats-v-dogs/training/"
VALIDATION_DIR = "C:/Users/alasmar/Downloads/cats-v-dogs/validation/"
TRAINING_CATS = os.path.join(TRAINING_DIR, "cats/")
VALIDATION_CATS = os.path.join(VALIDATION_DIR, "cats/")
TRAINING_DOGS = os.path.join(TRAINING_DIR, "dogs/")
VALIDATION_DOGS = os.path.join(VALIDATION_DIR, "dogs/")
# Define whether to include test split or not
INCLUDE_TEST = True
def split_data(main_dir, training_dir, validation_dir, split_size):
"""
Splits the data into train and test sets
Args:
main_dir (string): path containing the images
training_dir (string): path to be used for training
validation_dir (string): path to be used for validation
split_size (float): size of the dataset to be used for training
"""
files = []
for file in os.listdir(main_dir):
if os.path.getsize(os.path.join(main_dir, file)): # check if the file's size isn't 0
files.append(file) # appends file name to a list
shuffled_files = random.sample(files, len(files)) # shuffles the data
split = int(0.9 * len(shuffled_files)) #the training split casted into int for numeric rounding
train = shuffled_files[:split] #training split
validation = shuffled_files[split:] # validation split
for element in train:
copyfile(os.path.join(main_dir, element), os.path.join(training_dir, element)) # copy files into training directory
for element in validation:
copyfile(os.path.join(main_dir, element), os.path.join(validation_dir, element))# copy files into validation directory
split_data(CAT_DIR,'C:/Users/alasmar/Downloads/cats-v-dogs/training/cats','C:/Users/alasmar/Downloads/cats-v-dogs/validation/cats', 0.9)
split_data(DOG_DIR, 'C:/Users/alasmar/Downloads/cats-v-dogs/training/dogs','C:/Users/alasmar/Downloads/cats-v-dogs/validation/dogs', 0.9)
train_gen = ImageDataGenerator(
rescale=1./255)
validation_gen = ImageDataGenerator(
rescale=1./255.)
if INCLUDE_TEST:
test_gen = ImageDataGenerator(
rescale=1./255.)
train_generator = train_gen.flow_from_directory(
'C:/Users/alasmar/Downloads/cats-v-dogs/training',
target_size=(150, 150),
batch_size=64,
class_mode='binary')
validation_generator = validation_gen.flow_from_directory(
'C:/Users/alasmar/Downloads/cats-v-dogs/validation',
target_size=(150, 150),
batch_size=64,
class_mode='binary')
if INCLUDE_TEST:
test_generator = test_gen.flow_from_directory(
'C:/Users/alasmar/Downloads/cats-v-dogs/validation',
target_size=(150, 150),
batch_size=64,
class_mode='binary')
Found 22498 images belonging to 2 classes. Found 2500 images belonging to 2 classes. Found 2500 images belonging to 2 classes.
def plot_data(generator, n_images):
"""
Plots random data from dataset
Args:
generator: a generator instance
n_images : number of images to plot
"""
i = 1
images, labels = generator.next()
labels = labels.astype('int32')
plt.figure(figsize=(14, 15))
for image, label in zip(images, labels):
plt.subplot(4, 3, i)
plt.imshow(image)
plt.title(class_names[label])
plt.axis('off')
i += 1
if i == n_images:
break
plt.show()
plot_data(train_generator,7)
plot_data(validation_generator,7)
if INCLUDE_TEST:
plot_data(test_generator, 10)
inputs = tf.keras.layers.Input(shape=(150,150,3))
x = tf.keras.layers.Conv2D(32, (3,3), activation='relu')(inputs)
x = tf.keras.layers.Conv2D(64, (3,3), activation='relu')(x)
x = tf.keras.layers.MaxPooling2D(2,2)(x)
x = tf.keras.layers.Conv2D(64, (3,3), activation='relu')(x)
x = tf.keras.layers.Conv2D(128, (3,3), activation='relu')(x)
x = tf.keras.layers.MaxPooling2D(2,2)(x)
x = tf.keras.layers.Conv2D(128, (3,3), activation='relu')(x)
x = tf.keras.layers.Conv2D(256, (3,3), activation='relu')(x)
x = tf.keras.layers.GlobalAveragePooling2D()(x)
x = Dense(1024,activation='relu')(x)
x = tf.keras.layers.Dense(2, activation='softmax')(x)
model = Model(inputs=inputs, outputs=x)
model.compile(optimizer=tf.keras.optimizers.RMSprop(learning_rate=0.001),
loss='sparse_categorical_crossentropy',
metrics = ['accuracy'])
r = model.fit(
train_generator,
epochs=5,
validation_data=validation_generator)
Epoch 1/5 280/352 [======================>.......] - ETA: 8:16 - loss: 0.6898 - accuracy: 0.5618
C:\Users\alasmar\AppData\Local\Programs\Python\Python310\lib\site-packages\PIL\TiffImagePlugin.py:845: UserWarning: Truncated File Read
352/352 [==============================] - 2468s 7s/step - loss: 0.6852 - accuracy: 0.5720 - val_loss: 0.6539 - val_accuracy: 0.6348 Epoch 2/5 352/352 [==============================] - 1943s 6s/step - loss: 0.6359 - accuracy: 0.6502 - val_loss: 0.6414 - val_accuracy: 0.6252 Epoch 3/5 352/352 [==============================] - 1886s 5s/step - loss: 0.5943 - accuracy: 0.6882 - val_loss: 0.5499 - val_accuracy: 0.7372 Epoch 4/5 352/352 [==============================] - 1795s 5s/step - loss: 0.5525 - accuracy: 0.7308 - val_loss: 0.6257 - val_accuracy: 0.6524 Epoch 5/5 352/352 [==============================] - 1906s 5s/step - loss: 0.5240 - accuracy: 0.7478 - val_loss: 0.4896 - val_accuracy: 0.7544
if INCLUDE_TEST:
model.evaluate(test_generator)
40/40 [==============================] - 50s 1s/step - loss: 0.4896 - accuracy: 0.7544
def plot_prediction(generator, n_images):
"""
Test the model on random predictions
Args:
generator: a generator instance
n_images : number of images to plot
"""
i = 1
# Get the images and the labels from the generator
images, labels = generator.next()
# Gets the model predictions
preds = model.predict(images)
predictions = np.argmax(preds, axis=1)
labels = labels.astype('int32')
plt.figure(figsize=(14, 15))
for image, label in zip(images, labels):
plt.subplot(4, 3, i)
plt.imshow(image)
if predictions[i] == labels[i]:
title_obj = plt.title(class_names[label])
plt.setp(title_obj, color='g')
plt.axis('off')
else:
title_obj = plt.title(class_names[label])
plt.setp(title_obj, color='r')
plt.axis('off')
i += 1
if i == n_images:
break
plt.show()
if INCLUDE_TEST:
plot_prediction(test_generator, 10)
2/2 [==============================] - 1s 604ms/step
plot_prediction(validation_generator, 10)
2/2 [==============================] - 1s 599ms/step
# Create a model to visualize activation maps
gp_weights = model.get_layer('dense').get_weights()[0]
activation_model = Model(model.inputs, outputs=(model.get_layer('conv2d_5').output, model.get_layer('dense_1').output))
# Use the model to make predictions on the test generator
images, _ = test_generator.next()
features, results = activation_model.predict(images)
2/2 [==============================] - 1s 574ms/step
def show_cam(image_index, features, results):
"""
Shows activation maps
Args:
image_index: index of image
features: the extracted features
results: model's predictions
"""
# takes the features of the chosen image
features_for_img = features[image_index,:,:,:]
# get the class with the highest output probability
prediction = np.argmax(results[image_index])
# get the gap weights at the predicted class
class_activation_weights = gp_weights[:,prediction]
# upsample the features to the image's original size (150 x 150)
class_activation_features = sp.ndimage.zoom(features_for_img, (150/30, 150/30, 1), order=2)
# compute the intensity of each feature in the CAM
cam_output = np.dot(class_activation_features,class_activation_weights)
print('Predicted Class = ' +str(class_names[prediction])+ ', Probability = ' + str(results[image_index][prediction]))
# show the upsampled image
plt.imshow(images[image_index])
# strongly classified (95% probability) images will be in green, else red
if results[image_index][prediction]>0.95:
cmap_str = 'Greens'
else:
cmap_str = 'Blues'
# overlay the cam output
plt.imshow(cam_output, cmap=cmap_str, alpha=0.5)
# display the image
plt.show()
def show_maps(desired_class, num_maps):
'''
goes through the first 10,000 test images and generates Cam activation maps
Args:
desired_class: class to show the maps for
num_maps: number of maps to be generated
'''
counter = 0
# go through the first 10000 images
for i in range(0,10000):
# break if we already displayed the specified number of maps
if counter == num_maps:
break
# images that match the class will be shown
if np.argmax(results[i]) == desired_class:
counter += 1
show_cam(i,features, results)
show_maps(desired_class=1, num_maps=5)
Predicted Class = Dog, Probability = 0.5200827
Predicted Class = Dog, Probability = 0.6769477
Predicted Class = Dog, Probability = 0.9477724
Predicted Class = Dog, Probability = 0.8664233
Predicted Class = Dog, Probability = 0.5737325
show_maps(desired_class=0, num_maps=5)
Predicted Class = Cat, Probability = 0.65568477
Predicted Class = Cat, Probability = 0.78922504
Predicted Class = Cat, Probability = 0.8550956
Predicted Class = Cat, Probability = 0.9108136
Predicted Class = Cat, Probability = 0.73102206
results = pd.DataFrame(r.history)
results.tail()
| loss | accuracy | val_loss | val_accuracy | |
|---|---|---|---|---|
| 0 | 0.685154 | 0.571962 | 0.653850 | 0.6348 |
| 1 | 0.635894 | 0.650191 | 0.641383 | 0.6252 |
| 2 | 0.594305 | 0.688239 | 0.549863 | 0.7372 |
| 3 | 0.552515 | 0.730776 | 0.625722 | 0.6524 |
| 4 | 0.524021 | 0.747755 | 0.489643 | 0.7544 |
fig = px.line(results,y=[results['accuracy'],results['val_accuracy']],template="seaborn",color_discrete_sequence=['#fad25a','red'])
fig.update_layout(
title_font_color="#fad25a",
xaxis=dict(color="#fad25a",title='Epochs'),
yaxis=dict(color="#fad25a")
)
fig.show()
fig = px.line(results,y=[results['loss'],results['val_loss']],template="seaborn",color_discrete_sequence=['#fad25a','red'])
fig.update_layout(
title_font_color="#fad25a",
xaxis=dict(color="#fad25a",title='Epochs'),
yaxis=dict(color="#fad25a")
)
fig.show()
train_datagen = ImageDataGenerator(rescale = 1./255.,
rotation_range = 40,
width_shift_range = 0.2,
height_shift_range = 0.2,
shear_range = 0.2,
zoom_range = 0.2,
horizontal_flip = True)
valid_datagen = ImageDataGenerator( rescale = 1.0/255. )
# Flow training images in batches of 20 using train_datagen generator
train_generator = train_datagen.flow_from_directory('C:/Users/alasmar/Downloads/cats-v-dogs/training',
batch_size = 64,
class_mode = 'binary',
target_size = (150, 150))
validation_generator = valid_datagen.flow_from_directory( 'C:/Users/alasmar/Downloads/cats-v-dogs/validation',
batch_size = 64,
class_mode = 'binary',
target_size = (150, 150))
Found 22498 images belonging to 2 classes. Found 2500 images belonging to 2 classes.
test_gen = ImageDataGenerator(
rescale=1./255.)
test_generator = test_gen.flow_from_directory(
'C:/Users/alasmar/Downloads/cats-v-dogs/validation',
target_size=(150, 150),
batch_size=64,
class_mode='binary')
Found 2500 images belonging to 2 classes.
#Load Model
inception = tf.keras.applications.InceptionV3(weights='imagenet',include_top=False,input_shape=(150,150,3))
for layer in inception.layers[:-10]:
layer.trainable = False # Freeze weights of all layers till except the last 10
last_layer = inception.get_layer('mixed7')
print('last layer output shape: ', last_layer.output_shape)
layer_output = last_layer.output
last layer output shape: (None, 7, 7, 768)
x = Flatten()(layer_output)
x = BatchNormalization()(x)
x = Dense(1024, activation='relu')(x)
x = Dropout(0.2)(x)
predictions = Dense(2, activation='softmax')(x)
model = Model(inception.input, predictions)
model.summary()
Model: "model_2"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_2 (InputLayer) [(None, 150, 150, 3 0 []
)]
conv2d_6 (Conv2D) (None, 74, 74, 32) 864 ['input_2[0][0]']
batch_normalization (BatchNorm (None, 74, 74, 32) 96 ['conv2d_6[0][0]']
alization)
activation (Activation) (None, 74, 74, 32) 0 ['batch_normalization[0][0]']
conv2d_7 (Conv2D) (None, 72, 72, 32) 9216 ['activation[0][0]']
batch_normalization_1 (BatchNo (None, 72, 72, 32) 96 ['conv2d_7[0][0]']
rmalization)
activation_1 (Activation) (None, 72, 72, 32) 0 ['batch_normalization_1[0][0]']
conv2d_8 (Conv2D) (None, 72, 72, 64) 18432 ['activation_1[0][0]']
batch_normalization_2 (BatchNo (None, 72, 72, 64) 192 ['conv2d_8[0][0]']
rmalization)
activation_2 (Activation) (None, 72, 72, 64) 0 ['batch_normalization_2[0][0]']
max_pooling2d_2 (MaxPooling2D) (None, 35, 35, 64) 0 ['activation_2[0][0]']
conv2d_9 (Conv2D) (None, 35, 35, 80) 5120 ['max_pooling2d_2[0][0]']
batch_normalization_3 (BatchNo (None, 35, 35, 80) 240 ['conv2d_9[0][0]']
rmalization)
activation_3 (Activation) (None, 35, 35, 80) 0 ['batch_normalization_3[0][0]']
conv2d_10 (Conv2D) (None, 33, 33, 192) 138240 ['activation_3[0][0]']
batch_normalization_4 (BatchNo (None, 33, 33, 192) 576 ['conv2d_10[0][0]']
rmalization)
activation_4 (Activation) (None, 33, 33, 192) 0 ['batch_normalization_4[0][0]']
max_pooling2d_3 (MaxPooling2D) (None, 16, 16, 192) 0 ['activation_4[0][0]']
conv2d_14 (Conv2D) (None, 16, 16, 64) 12288 ['max_pooling2d_3[0][0]']
batch_normalization_8 (BatchNo (None, 16, 16, 64) 192 ['conv2d_14[0][0]']
rmalization)
activation_8 (Activation) (None, 16, 16, 64) 0 ['batch_normalization_8[0][0]']
conv2d_12 (Conv2D) (None, 16, 16, 48) 9216 ['max_pooling2d_3[0][0]']
conv2d_15 (Conv2D) (None, 16, 16, 96) 55296 ['activation_8[0][0]']
batch_normalization_6 (BatchNo (None, 16, 16, 48) 144 ['conv2d_12[0][0]']
rmalization)
batch_normalization_9 (BatchNo (None, 16, 16, 96) 288 ['conv2d_15[0][0]']
rmalization)
activation_6 (Activation) (None, 16, 16, 48) 0 ['batch_normalization_6[0][0]']
activation_9 (Activation) (None, 16, 16, 96) 0 ['batch_normalization_9[0][0]']
average_pooling2d (AveragePool (None, 16, 16, 192) 0 ['max_pooling2d_3[0][0]']
ing2D)
conv2d_11 (Conv2D) (None, 16, 16, 64) 12288 ['max_pooling2d_3[0][0]']
conv2d_13 (Conv2D) (None, 16, 16, 64) 76800 ['activation_6[0][0]']
conv2d_16 (Conv2D) (None, 16, 16, 96) 82944 ['activation_9[0][0]']
conv2d_17 (Conv2D) (None, 16, 16, 32) 6144 ['average_pooling2d[0][0]']
batch_normalization_5 (BatchNo (None, 16, 16, 64) 192 ['conv2d_11[0][0]']
rmalization)
batch_normalization_7 (BatchNo (None, 16, 16, 64) 192 ['conv2d_13[0][0]']
rmalization)
batch_normalization_10 (BatchN (None, 16, 16, 96) 288 ['conv2d_16[0][0]']
ormalization)
batch_normalization_11 (BatchN (None, 16, 16, 32) 96 ['conv2d_17[0][0]']
ormalization)
activation_5 (Activation) (None, 16, 16, 64) 0 ['batch_normalization_5[0][0]']
activation_7 (Activation) (None, 16, 16, 64) 0 ['batch_normalization_7[0][0]']
activation_10 (Activation) (None, 16, 16, 96) 0 ['batch_normalization_10[0][0]']
activation_11 (Activation) (None, 16, 16, 32) 0 ['batch_normalization_11[0][0]']
mixed0 (Concatenate) (None, 16, 16, 256) 0 ['activation_5[0][0]',
'activation_7[0][0]',
'activation_10[0][0]',
'activation_11[0][0]']
conv2d_21 (Conv2D) (None, 16, 16, 64) 16384 ['mixed0[0][0]']
batch_normalization_15 (BatchN (None, 16, 16, 64) 192 ['conv2d_21[0][0]']
ormalization)
activation_15 (Activation) (None, 16, 16, 64) 0 ['batch_normalization_15[0][0]']
conv2d_19 (Conv2D) (None, 16, 16, 48) 12288 ['mixed0[0][0]']
conv2d_22 (Conv2D) (None, 16, 16, 96) 55296 ['activation_15[0][0]']
batch_normalization_13 (BatchN (None, 16, 16, 48) 144 ['conv2d_19[0][0]']
ormalization)
batch_normalization_16 (BatchN (None, 16, 16, 96) 288 ['conv2d_22[0][0]']
ormalization)
activation_13 (Activation) (None, 16, 16, 48) 0 ['batch_normalization_13[0][0]']
activation_16 (Activation) (None, 16, 16, 96) 0 ['batch_normalization_16[0][0]']
average_pooling2d_1 (AveragePo (None, 16, 16, 256) 0 ['mixed0[0][0]']
oling2D)
conv2d_18 (Conv2D) (None, 16, 16, 64) 16384 ['mixed0[0][0]']
conv2d_20 (Conv2D) (None, 16, 16, 64) 76800 ['activation_13[0][0]']
conv2d_23 (Conv2D) (None, 16, 16, 96) 82944 ['activation_16[0][0]']
conv2d_24 (Conv2D) (None, 16, 16, 64) 16384 ['average_pooling2d_1[0][0]']
batch_normalization_12 (BatchN (None, 16, 16, 64) 192 ['conv2d_18[0][0]']
ormalization)
batch_normalization_14 (BatchN (None, 16, 16, 64) 192 ['conv2d_20[0][0]']
ormalization)
batch_normalization_17 (BatchN (None, 16, 16, 96) 288 ['conv2d_23[0][0]']
ormalization)
batch_normalization_18 (BatchN (None, 16, 16, 64) 192 ['conv2d_24[0][0]']
ormalization)
activation_12 (Activation) (None, 16, 16, 64) 0 ['batch_normalization_12[0][0]']
activation_14 (Activation) (None, 16, 16, 64) 0 ['batch_normalization_14[0][0]']
activation_17 (Activation) (None, 16, 16, 96) 0 ['batch_normalization_17[0][0]']
activation_18 (Activation) (None, 16, 16, 64) 0 ['batch_normalization_18[0][0]']
mixed1 (Concatenate) (None, 16, 16, 288) 0 ['activation_12[0][0]',
'activation_14[0][0]',
'activation_17[0][0]',
'activation_18[0][0]']
conv2d_28 (Conv2D) (None, 16, 16, 64) 18432 ['mixed1[0][0]']
batch_normalization_22 (BatchN (None, 16, 16, 64) 192 ['conv2d_28[0][0]']
ormalization)
activation_22 (Activation) (None, 16, 16, 64) 0 ['batch_normalization_22[0][0]']
conv2d_26 (Conv2D) (None, 16, 16, 48) 13824 ['mixed1[0][0]']
conv2d_29 (Conv2D) (None, 16, 16, 96) 55296 ['activation_22[0][0]']
batch_normalization_20 (BatchN (None, 16, 16, 48) 144 ['conv2d_26[0][0]']
ormalization)
batch_normalization_23 (BatchN (None, 16, 16, 96) 288 ['conv2d_29[0][0]']
ormalization)
activation_20 (Activation) (None, 16, 16, 48) 0 ['batch_normalization_20[0][0]']
activation_23 (Activation) (None, 16, 16, 96) 0 ['batch_normalization_23[0][0]']
average_pooling2d_2 (AveragePo (None, 16, 16, 288) 0 ['mixed1[0][0]']
oling2D)
conv2d_25 (Conv2D) (None, 16, 16, 64) 18432 ['mixed1[0][0]']
conv2d_27 (Conv2D) (None, 16, 16, 64) 76800 ['activation_20[0][0]']
conv2d_30 (Conv2D) (None, 16, 16, 96) 82944 ['activation_23[0][0]']
conv2d_31 (Conv2D) (None, 16, 16, 64) 18432 ['average_pooling2d_2[0][0]']
batch_normalization_19 (BatchN (None, 16, 16, 64) 192 ['conv2d_25[0][0]']
ormalization)
batch_normalization_21 (BatchN (None, 16, 16, 64) 192 ['conv2d_27[0][0]']
ormalization)
batch_normalization_24 (BatchN (None, 16, 16, 96) 288 ['conv2d_30[0][0]']
ormalization)
batch_normalization_25 (BatchN (None, 16, 16, 64) 192 ['conv2d_31[0][0]']
ormalization)
activation_19 (Activation) (None, 16, 16, 64) 0 ['batch_normalization_19[0][0]']
activation_21 (Activation) (None, 16, 16, 64) 0 ['batch_normalization_21[0][0]']
activation_24 (Activation) (None, 16, 16, 96) 0 ['batch_normalization_24[0][0]']
activation_25 (Activation) (None, 16, 16, 64) 0 ['batch_normalization_25[0][0]']
mixed2 (Concatenate) (None, 16, 16, 288) 0 ['activation_19[0][0]',
'activation_21[0][0]',
'activation_24[0][0]',
'activation_25[0][0]']
conv2d_33 (Conv2D) (None, 16, 16, 64) 18432 ['mixed2[0][0]']
batch_normalization_27 (BatchN (None, 16, 16, 64) 192 ['conv2d_33[0][0]']
ormalization)
activation_27 (Activation) (None, 16, 16, 64) 0 ['batch_normalization_27[0][0]']
conv2d_34 (Conv2D) (None, 16, 16, 96) 55296 ['activation_27[0][0]']
batch_normalization_28 (BatchN (None, 16, 16, 96) 288 ['conv2d_34[0][0]']
ormalization)
activation_28 (Activation) (None, 16, 16, 96) 0 ['batch_normalization_28[0][0]']
conv2d_32 (Conv2D) (None, 7, 7, 384) 995328 ['mixed2[0][0]']
conv2d_35 (Conv2D) (None, 7, 7, 96) 82944 ['activation_28[0][0]']
batch_normalization_26 (BatchN (None, 7, 7, 384) 1152 ['conv2d_32[0][0]']
ormalization)
batch_normalization_29 (BatchN (None, 7, 7, 96) 288 ['conv2d_35[0][0]']
ormalization)
activation_26 (Activation) (None, 7, 7, 384) 0 ['batch_normalization_26[0][0]']
activation_29 (Activation) (None, 7, 7, 96) 0 ['batch_normalization_29[0][0]']
max_pooling2d_4 (MaxPooling2D) (None, 7, 7, 288) 0 ['mixed2[0][0]']
mixed3 (Concatenate) (None, 7, 7, 768) 0 ['activation_26[0][0]',
'activation_29[0][0]',
'max_pooling2d_4[0][0]']
conv2d_40 (Conv2D) (None, 7, 7, 128) 98304 ['mixed3[0][0]']
batch_normalization_34 (BatchN (None, 7, 7, 128) 384 ['conv2d_40[0][0]']
ormalization)
activation_34 (Activation) (None, 7, 7, 128) 0 ['batch_normalization_34[0][0]']
conv2d_41 (Conv2D) (None, 7, 7, 128) 114688 ['activation_34[0][0]']
batch_normalization_35 (BatchN (None, 7, 7, 128) 384 ['conv2d_41[0][0]']
ormalization)
activation_35 (Activation) (None, 7, 7, 128) 0 ['batch_normalization_35[0][0]']
conv2d_37 (Conv2D) (None, 7, 7, 128) 98304 ['mixed3[0][0]']
conv2d_42 (Conv2D) (None, 7, 7, 128) 114688 ['activation_35[0][0]']
batch_normalization_31 (BatchN (None, 7, 7, 128) 384 ['conv2d_37[0][0]']
ormalization)
batch_normalization_36 (BatchN (None, 7, 7, 128) 384 ['conv2d_42[0][0]']
ormalization)
activation_31 (Activation) (None, 7, 7, 128) 0 ['batch_normalization_31[0][0]']
activation_36 (Activation) (None, 7, 7, 128) 0 ['batch_normalization_36[0][0]']
conv2d_38 (Conv2D) (None, 7, 7, 128) 114688 ['activation_31[0][0]']
conv2d_43 (Conv2D) (None, 7, 7, 128) 114688 ['activation_36[0][0]']
batch_normalization_32 (BatchN (None, 7, 7, 128) 384 ['conv2d_38[0][0]']
ormalization)
batch_normalization_37 (BatchN (None, 7, 7, 128) 384 ['conv2d_43[0][0]']
ormalization)
activation_32 (Activation) (None, 7, 7, 128) 0 ['batch_normalization_32[0][0]']
activation_37 (Activation) (None, 7, 7, 128) 0 ['batch_normalization_37[0][0]']
average_pooling2d_3 (AveragePo (None, 7, 7, 768) 0 ['mixed3[0][0]']
oling2D)
conv2d_36 (Conv2D) (None, 7, 7, 192) 147456 ['mixed3[0][0]']
conv2d_39 (Conv2D) (None, 7, 7, 192) 172032 ['activation_32[0][0]']
conv2d_44 (Conv2D) (None, 7, 7, 192) 172032 ['activation_37[0][0]']
conv2d_45 (Conv2D) (None, 7, 7, 192) 147456 ['average_pooling2d_3[0][0]']
batch_normalization_30 (BatchN (None, 7, 7, 192) 576 ['conv2d_36[0][0]']
ormalization)
batch_normalization_33 (BatchN (None, 7, 7, 192) 576 ['conv2d_39[0][0]']
ormalization)
batch_normalization_38 (BatchN (None, 7, 7, 192) 576 ['conv2d_44[0][0]']
ormalization)
batch_normalization_39 (BatchN (None, 7, 7, 192) 576 ['conv2d_45[0][0]']
ormalization)
activation_30 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_30[0][0]']
activation_33 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_33[0][0]']
activation_38 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_38[0][0]']
activation_39 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_39[0][0]']
mixed4 (Concatenate) (None, 7, 7, 768) 0 ['activation_30[0][0]',
'activation_33[0][0]',
'activation_38[0][0]',
'activation_39[0][0]']
conv2d_50 (Conv2D) (None, 7, 7, 160) 122880 ['mixed4[0][0]']
batch_normalization_44 (BatchN (None, 7, 7, 160) 480 ['conv2d_50[0][0]']
ormalization)
activation_44 (Activation) (None, 7, 7, 160) 0 ['batch_normalization_44[0][0]']
conv2d_51 (Conv2D) (None, 7, 7, 160) 179200 ['activation_44[0][0]']
batch_normalization_45 (BatchN (None, 7, 7, 160) 480 ['conv2d_51[0][0]']
ormalization)
activation_45 (Activation) (None, 7, 7, 160) 0 ['batch_normalization_45[0][0]']
conv2d_47 (Conv2D) (None, 7, 7, 160) 122880 ['mixed4[0][0]']
conv2d_52 (Conv2D) (None, 7, 7, 160) 179200 ['activation_45[0][0]']
batch_normalization_41 (BatchN (None, 7, 7, 160) 480 ['conv2d_47[0][0]']
ormalization)
batch_normalization_46 (BatchN (None, 7, 7, 160) 480 ['conv2d_52[0][0]']
ormalization)
activation_41 (Activation) (None, 7, 7, 160) 0 ['batch_normalization_41[0][0]']
activation_46 (Activation) (None, 7, 7, 160) 0 ['batch_normalization_46[0][0]']
conv2d_48 (Conv2D) (None, 7, 7, 160) 179200 ['activation_41[0][0]']
conv2d_53 (Conv2D) (None, 7, 7, 160) 179200 ['activation_46[0][0]']
batch_normalization_42 (BatchN (None, 7, 7, 160) 480 ['conv2d_48[0][0]']
ormalization)
batch_normalization_47 (BatchN (None, 7, 7, 160) 480 ['conv2d_53[0][0]']
ormalization)
activation_42 (Activation) (None, 7, 7, 160) 0 ['batch_normalization_42[0][0]']
activation_47 (Activation) (None, 7, 7, 160) 0 ['batch_normalization_47[0][0]']
average_pooling2d_4 (AveragePo (None, 7, 7, 768) 0 ['mixed4[0][0]']
oling2D)
conv2d_46 (Conv2D) (None, 7, 7, 192) 147456 ['mixed4[0][0]']
conv2d_49 (Conv2D) (None, 7, 7, 192) 215040 ['activation_42[0][0]']
conv2d_54 (Conv2D) (None, 7, 7, 192) 215040 ['activation_47[0][0]']
conv2d_55 (Conv2D) (None, 7, 7, 192) 147456 ['average_pooling2d_4[0][0]']
batch_normalization_40 (BatchN (None, 7, 7, 192) 576 ['conv2d_46[0][0]']
ormalization)
batch_normalization_43 (BatchN (None, 7, 7, 192) 576 ['conv2d_49[0][0]']
ormalization)
batch_normalization_48 (BatchN (None, 7, 7, 192) 576 ['conv2d_54[0][0]']
ormalization)
batch_normalization_49 (BatchN (None, 7, 7, 192) 576 ['conv2d_55[0][0]']
ormalization)
activation_40 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_40[0][0]']
activation_43 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_43[0][0]']
activation_48 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_48[0][0]']
activation_49 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_49[0][0]']
mixed5 (Concatenate) (None, 7, 7, 768) 0 ['activation_40[0][0]',
'activation_43[0][0]',
'activation_48[0][0]',
'activation_49[0][0]']
conv2d_60 (Conv2D) (None, 7, 7, 160) 122880 ['mixed5[0][0]']
batch_normalization_54 (BatchN (None, 7, 7, 160) 480 ['conv2d_60[0][0]']
ormalization)
activation_54 (Activation) (None, 7, 7, 160) 0 ['batch_normalization_54[0][0]']
conv2d_61 (Conv2D) (None, 7, 7, 160) 179200 ['activation_54[0][0]']
batch_normalization_55 (BatchN (None, 7, 7, 160) 480 ['conv2d_61[0][0]']
ormalization)
activation_55 (Activation) (None, 7, 7, 160) 0 ['batch_normalization_55[0][0]']
conv2d_57 (Conv2D) (None, 7, 7, 160) 122880 ['mixed5[0][0]']
conv2d_62 (Conv2D) (None, 7, 7, 160) 179200 ['activation_55[0][0]']
batch_normalization_51 (BatchN (None, 7, 7, 160) 480 ['conv2d_57[0][0]']
ormalization)
batch_normalization_56 (BatchN (None, 7, 7, 160) 480 ['conv2d_62[0][0]']
ormalization)
activation_51 (Activation) (None, 7, 7, 160) 0 ['batch_normalization_51[0][0]']
activation_56 (Activation) (None, 7, 7, 160) 0 ['batch_normalization_56[0][0]']
conv2d_58 (Conv2D) (None, 7, 7, 160) 179200 ['activation_51[0][0]']
conv2d_63 (Conv2D) (None, 7, 7, 160) 179200 ['activation_56[0][0]']
batch_normalization_52 (BatchN (None, 7, 7, 160) 480 ['conv2d_58[0][0]']
ormalization)
batch_normalization_57 (BatchN (None, 7, 7, 160) 480 ['conv2d_63[0][0]']
ormalization)
activation_52 (Activation) (None, 7, 7, 160) 0 ['batch_normalization_52[0][0]']
activation_57 (Activation) (None, 7, 7, 160) 0 ['batch_normalization_57[0][0]']
average_pooling2d_5 (AveragePo (None, 7, 7, 768) 0 ['mixed5[0][0]']
oling2D)
conv2d_56 (Conv2D) (None, 7, 7, 192) 147456 ['mixed5[0][0]']
conv2d_59 (Conv2D) (None, 7, 7, 192) 215040 ['activation_52[0][0]']
conv2d_64 (Conv2D) (None, 7, 7, 192) 215040 ['activation_57[0][0]']
conv2d_65 (Conv2D) (None, 7, 7, 192) 147456 ['average_pooling2d_5[0][0]']
batch_normalization_50 (BatchN (None, 7, 7, 192) 576 ['conv2d_56[0][0]']
ormalization)
batch_normalization_53 (BatchN (None, 7, 7, 192) 576 ['conv2d_59[0][0]']
ormalization)
batch_normalization_58 (BatchN (None, 7, 7, 192) 576 ['conv2d_64[0][0]']
ormalization)
batch_normalization_59 (BatchN (None, 7, 7, 192) 576 ['conv2d_65[0][0]']
ormalization)
activation_50 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_50[0][0]']
activation_53 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_53[0][0]']
activation_58 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_58[0][0]']
activation_59 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_59[0][0]']
mixed6 (Concatenate) (None, 7, 7, 768) 0 ['activation_50[0][0]',
'activation_53[0][0]',
'activation_58[0][0]',
'activation_59[0][0]']
conv2d_70 (Conv2D) (None, 7, 7, 192) 147456 ['mixed6[0][0]']
batch_normalization_64 (BatchN (None, 7, 7, 192) 576 ['conv2d_70[0][0]']
ormalization)
activation_64 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_64[0][0]']
conv2d_71 (Conv2D) (None, 7, 7, 192) 258048 ['activation_64[0][0]']
batch_normalization_65 (BatchN (None, 7, 7, 192) 576 ['conv2d_71[0][0]']
ormalization)
activation_65 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_65[0][0]']
conv2d_67 (Conv2D) (None, 7, 7, 192) 147456 ['mixed6[0][0]']
conv2d_72 (Conv2D) (None, 7, 7, 192) 258048 ['activation_65[0][0]']
batch_normalization_61 (BatchN (None, 7, 7, 192) 576 ['conv2d_67[0][0]']
ormalization)
batch_normalization_66 (BatchN (None, 7, 7, 192) 576 ['conv2d_72[0][0]']
ormalization)
activation_61 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_61[0][0]']
activation_66 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_66[0][0]']
conv2d_68 (Conv2D) (None, 7, 7, 192) 258048 ['activation_61[0][0]']
conv2d_73 (Conv2D) (None, 7, 7, 192) 258048 ['activation_66[0][0]']
batch_normalization_62 (BatchN (None, 7, 7, 192) 576 ['conv2d_68[0][0]']
ormalization)
batch_normalization_67 (BatchN (None, 7, 7, 192) 576 ['conv2d_73[0][0]']
ormalization)
activation_62 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_62[0][0]']
activation_67 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_67[0][0]']
average_pooling2d_6 (AveragePo (None, 7, 7, 768) 0 ['mixed6[0][0]']
oling2D)
conv2d_66 (Conv2D) (None, 7, 7, 192) 147456 ['mixed6[0][0]']
conv2d_69 (Conv2D) (None, 7, 7, 192) 258048 ['activation_62[0][0]']
conv2d_74 (Conv2D) (None, 7, 7, 192) 258048 ['activation_67[0][0]']
conv2d_75 (Conv2D) (None, 7, 7, 192) 147456 ['average_pooling2d_6[0][0]']
batch_normalization_60 (BatchN (None, 7, 7, 192) 576 ['conv2d_66[0][0]']
ormalization)
batch_normalization_63 (BatchN (None, 7, 7, 192) 576 ['conv2d_69[0][0]']
ormalization)
batch_normalization_68 (BatchN (None, 7, 7, 192) 576 ['conv2d_74[0][0]']
ormalization)
batch_normalization_69 (BatchN (None, 7, 7, 192) 576 ['conv2d_75[0][0]']
ormalization)
activation_60 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_60[0][0]']
activation_63 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_63[0][0]']
activation_68 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_68[0][0]']
activation_69 (Activation) (None, 7, 7, 192) 0 ['batch_normalization_69[0][0]']
mixed7 (Concatenate) (None, 7, 7, 768) 0 ['activation_60[0][0]',
'activation_63[0][0]',
'activation_68[0][0]',
'activation_69[0][0]']
flatten (Flatten) (None, 37632) 0 ['mixed7[0][0]']
batch_normalization_94 (BatchN (None, 37632) 150528 ['flatten[0][0]']
ormalization)
dense_2 (Dense) (None, 1024) 38536192 ['batch_normalization_94[0][0]']
dropout (Dropout) (None, 1024) 0 ['dense_2[0][0]']
dense_3 (Dense) (None, 2) 2050 ['dropout[0][0]']
==================================================================================================
Total params: 47,664,034
Trainable params: 38,613,506
Non-trainable params: 9,050,528
__________________________________________________________________________________________________
def scheduler(epoch, lr):
if epoch < 20:
return lr
else:
return lr * tf.math.exp(-0.2)
callback = tf.keras.callbacks.LearningRateScheduler(scheduler) # set the callback to our scheduler function
# Set the training parameters
model.compile(optimizer = tf.keras.optimizers.RMSprop(learning_rate=0.0001),
loss = 'sparse_categorical_crossentropy',
metrics = ['accuracy'])
history = model.fit(
train_generator,
validation_data = validation_generator,
epochs = 5,callbacks=[callback])
Epoch 1/5 55/352 [===>..........................] - ETA: 8:21 - loss: 0.4713 - accuracy: 0.8797
C:\Users\alasmar\AppData\Local\Programs\Python\Python310\lib\site-packages\PIL\TiffImagePlugin.py:845: UserWarning: Truncated File Read
352/352 [==============================] - 631s 2s/step - loss: 0.3665 - accuracy: 0.9112 - val_loss: 0.1978 - val_accuracy: 0.9564 - lr: 1.0000e-04 Epoch 2/5 352/352 [==============================] - 610s 2s/step - loss: 0.2878 - accuracy: 0.9269 - val_loss: 0.2882 - val_accuracy: 0.9496 - lr: 1.0000e-04 Epoch 3/5 352/352 [==============================] - 590s 2s/step - loss: 0.2395 - accuracy: 0.9344 - val_loss: 0.2465 - val_accuracy: 0.9584 - lr: 1.0000e-04 Epoch 4/5 352/352 [==============================] - 577s 2s/step - loss: 0.2146 - accuracy: 0.9404 - val_loss: 0.2291 - val_accuracy: 0.9608 - lr: 1.0000e-04 Epoch 5/5 352/352 [==============================] - 594s 2s/step - loss: 0.1820 - accuracy: 0.9430 - val_loss: 0.2573 - val_accuracy: 0.9708 - lr: 1.0000e-04
plot_prediction(validation_generator, 10)
2/2 [==============================] - 2s 434ms/step
images, labels = validation_generator.next()
def calculate_gradients(images, labels, index):
"""
Computes gradient of the loss with respect to the input image
Args:
Images: numpy array containing images of shape (n,150,150,3)
labels: numpy array containing labels shape(n,)
index: index of the image
"""
# get image of the given index and add 1 to it's first dimension
image = np.expand_dims(images[index],axis=0)
#convert image to tensor
image_tensor = tf.convert_to_tensor(image)
# get the class of the given label and convert it to an integer
class_index = int(labels[index])
# one hot encode the labels
true_value = tf.one_hot([class_index] * image.shape[0], 2)
# compute the gradient of the loss
with tf.GradientTape() as tape:
# Watch the input image
tape.watch(image_tensor)
# Generate predictions
pred = model(image_tensor)
# Compute loss
loss = tf.keras.losses.categorical_crossentropy(true_value, pred)
# Get the gradient with respect to the image
gradients = tape.gradient(loss, image_tensor)
grey_scale_gradients = tf.reduce_sum(tf.abs(gradients),axis=-1)
normalized_gradients = (255*(grey_scale_gradients - tf.reduce_min(grey_scale_gradients))/
(tf.reduce_max(grey_scale_gradients) - tf.reduce_min(grey_scale_gradients)))
normalized_gradients = tf.squeeze(normalized_gradients)
normalized_gradients = tf.cast(normalized_gradients, tf.uint8)
return normalized_gradients,pred
def show_saliency(images, labels, n_images):
"""
plot saliency maps
Args:
Images: numpy array containing images of shape (n,150,150,3)
labels: numpy array containing labels shape(n,)
n_images: number of images to plot
"""
# Loop for number of images specified
for i in range(n_images):
# Computes gradient of the loss with respect to the input image
gradients,prediction = calculate_gradients(images, labels, i)
prediction = np.argmax(prediction)
# Colorize greyscale gradients
gradient_color = cv2.applyColorMap(gradients.numpy(), cv2.COLORMAP_HOT)
#Normalize the colored gradients
gradient_color = gradient_color / 255.0
# Super impose colored gradients on the image
super_imposed = cv2.addWeighted(images[i], 0.6, gradient_color, 0.5, 0.1, dtype = cv2.CV_64F)
print('Predicted Class: ' +str(class_names[prediction]+",\t"+ f'True Class: {class_names[int(labels[i])]}'))
plt.figure(figsize=(8, 8))
plt.imshow(super_imposed)
plt.axis('off')
plt.show()
show_saliency(images, labels, 5)
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Predicted Class: Dog, True Class: Dog
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Predicted Class: Cat, True Class: Cat
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Predicted Class: Cat, True Class: Cat
Predicted Class: Dog, True Class: Dog
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Predicted Class: Cat, True Class: Cat
results = pd.DataFrame(history.history)
results.tail()
| loss | accuracy | val_loss | val_accuracy | lr | |
|---|---|---|---|---|---|
| 0 | 0.366455 | 0.911237 | 0.197829 | 0.9564 | 0.0001 |
| 1 | 0.287796 | 0.926927 | 0.288203 | 0.9496 | 0.0001 |
| 2 | 0.239462 | 0.934439 | 0.246468 | 0.9584 | 0.0001 |
| 3 | 0.214561 | 0.940395 | 0.229127 | 0.9608 | 0.0001 |
| 4 | 0.182025 | 0.942973 | 0.257326 | 0.9708 | 0.0001 |
fig = px.line(results,y=[results['accuracy'],results['val_accuracy']],template="plotly_dark",color_discrete_sequence=['#F67280','#DD2706'])
fig.update_layout(
title_font_color="#41BEE9",
xaxis=dict(color="#41BEE9",title='Epochs'),
yaxis=dict(color="#41BEE9")
)
fig.show()
fig = px.line(results,y=[results['loss'],results['val_loss']],template="plotly_dark",color_discrete_sequence=['#F67280','#DD2706'])
fig.update_layout(
title_font_color="#41BEE9",
xaxis=dict(color="#41BEE9",title='Epochs'),
yaxis=dict(color="#41BEE9")
)
fig.show()